import axios from 'axios'
import VAxios from './Axios.js'
import router from '@/router/index.js'
import storage from '@/utils/storage.js'
import BASE_URL from './baseConfig.js'
import { Message, MessageBox } from 'element-ui'
import { setObjToUrlParams } from '@/utils/common.js'
import { checkStatus } from './checkStatus.js'
import { ACCESS_TOKEN } from '@/store/mutationTypes.js'

const codeEnum = {
  SUCCESS: 200, // 成功code
  // ERROR: 400 || 401 || 404 || 101, // 错误code
  FAIL: 400 || 401 || 404 || 500,
  TIMEOUT: 10042 // 登录超时code
}

// 常用的contentType类型
const contentTypeEnum = {
  JSON: 'application/json;charset=UTF-8',
  TEXT: 'text/plain;charset=UTF-8',
  FORM_URLENCODED: 'application/x-www-form-urlencoded;charset=UTF-8',
  FORM_DATA: 'multipart/form-data;charset=UTF-8'
}

// 请求方法
const requestEnum = {
  GET: 'GET',
  POST: 'POST',
  PATCH: 'PATCH',
  PUT: 'PUT',
  DELETE: 'DELETE'
}

const transform = {
  // 请求前处理config
  beforeRequestHook: (config, options) => {
    const { apiUrl, postJoinParamsToUrl } = options
    config.url = apiUrl ? apiUrl + config.url : config.url
    // post请求--参数需要拼接到url后面
    if (config.method.toUpperCase() === requestEnum.POST && postJoinParamsToUrl) {
      config.url = setObjToUrlParams(config.url, config.data)
    }
    return config
  },

  // 请求拦截器--处理config中的token
  requestInterceptors: (config) => {
    // 将token携带在headers中
    const token = storage.get(ACCESS_TOKEN)
    if (token) {
      config.headers.token = token
    }
    return config
  },

  // 处理响应数据
  transformRequest: async (res, options) => {
    const reject = Promise.reject
    const { isTransformResult, isShowMessage = true, isShowSuccessMessage, isShowErrorMessage, successMessageText, errorMessageText, errorMessageBox } = options
    // console.log(res)
    // axios返回的请求结果
    const { status, data: response } = res
    // code、data、desc为后端统一返回的字段
    const { code, data, desc } = response

    // 请求成功--此时只是请求成功，并不表示获取后端数据成功
    const statusSuccess = status === codeEnum.SUCCESS
    // 请求成功--此时成功获取后端返回的正确数据
    const responseSuccess = code === codeEnum.SUCCESS

    // 是否显示提示信息
    if (isShowMessage) {
      if (responseSuccess && (successMessageText || isShowSuccessMessage)) {
        // 成功提示信息
        Message.success(successMessageText || desc)
      } else if (!responseSuccess && (errorMessageText || isShowErrorMessage)) {
        // 失败提示信息
        Message.error(errorMessageText || desc)
      } else if (!responseSuccess && errorMessageBox === 'messageBox') {
        // 有时候需要弹出一些确认框的错误信息
        MessageBox.confirm('错误提示', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
      }
    }

    // 登录超时
    if (code === codeEnum.TIMEOUT) {
      // TODO:需要获取currentRoute中的name
      // 是登录页面不用重定向
      if (router.currentRoute.name === 'login') return
      console.log(router.currentRoute)
      // 重定向到登录页面
      const timeoutMessage = '登录超时，请重新登录！'
      const confirmRes = await MessageBox.confirm('登录身份已失效，请重新登录！', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).catch(error => error)
      if (confirmRes === 'confirm') {
        router.replace({
          name: 'login',
          query: {
            redirect: router.currentRoute.fullPath
          }
        })
        storage.clear()
      }
      return reject(new Error(timeoutMessage))
    }

    // 不进行任何处理，直接返回
    // 用户页面代码可能需要直接获取code、data、desc这些信息时
    if (!isTransformResult) return res.data

    // 请求成功--statues===200 && code === 200
    if (statusSuccess && responseSuccess) return data

    // 请求成功--但是后端数据返回不正确
    if (statusSuccess && !responseSuccess) {
      // 此时可能是由于错误请求
      if (code === codeEnum.FAIL) {
        const message = desc || '操作失败，系统异常！'
        Message.error(message)
        reject(new Error(message))
        return reject()
      }
      return null
    }

    // 最后将结果返回出去
    return data
  },

  // 相应错误处理
  responseInterceptorsCatch: (error) => {
    const { response, code, message } = error || {}
    const msg = response && response.data && response.data.message ? response.data.message : ''
    const err = error.toStrong()
    try {
      if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) {
        Message.error('接口请求超时，请刷新页面重试！')
        return
      }
      if (err && err.includes('Network Error')) {
        MessageBox.confirm('请检查您的网络连接是否正常', '网络异常', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'error'
        })
      }
    } catch (error) {
      throw new Error(error)
    }
    // 请求是否被取消
    const isCancel = axios.isCancel(error)
    if (!isCancel) {
      checkStatus(error.response && error.response.status, msg)
    } else {
      console.warn('请求被取消')
    }
    return error
  }
}

export const Axios = new VAxios({
  timeout: 15 * 1000,
  headers: { 'Content-Type': contentTypeEnum.JSON },
  transform,
  // 配置项--以下配置都能在独立的接口请求中被覆盖
  requestOptions: {
    // 是否需要对返回数据进行处理
    isTransformResult: true,
    // post请求的时候参数拼接在url上
    postJoinParamsToUrl: false,
    errorMessageBox: 'none',
    // 接口地址
    apiUrl: BASE_URL
  },
  // 表示跨域请求时是否需要使用凭证
  withCredentials: false
})
// 将request的this指向Axios
export default Axios.request.bind(Axios)
